Organising javascript in rails apps

26 views
Skip to first unread message

Steven Ringo

unread,
Jun 22, 2010, 7:50:20 AM6/22/10
to Ruby or Rails Oceania
Hi All,

Just wanted to find out how folks are organising javascript code &
files in rails apps, and address things such as:

1. Not polluting the global namespace. Seems to be divided opinion on
using object literals vs. prototypal inheritance vs. Crockford's
module pattern.
2. Separating code into files that are relevant to the server side
code e.g. hooking into rails' naming conventions, and having 1 js file
per view or controller.
3. Minifying and combining files in production.

There seem to be some nice tools to address point 3, like sprockets
and requirejs, but can't seem to find anything convincing about what
is the best way to handle 1. and 2.

Would be great to hear what you guys are using out there.

Thanks,

Steve

Julio Cesar Ody

unread,
Jun 22, 2010, 9:48:11 AM6/22/10
to rails-...@googlegroups.com
*ahem*

http://sydjs-architecting.heroku.com/

Write Javascript apps, not just random methods. Some exceptions apply.
I'm more of a module pattern kind of guy so that's my take. At the end
of the day, it's all a matter of how you like the source written.

As for number 2, not necessarily. Write your JS as a client to the
server's API. E.g.: a table you can use to read/write data is an app
in itself. While it may appear in, say, FruitsController#index, I
wouldn't have it mixed up with something else.

And as for 3, all the way. If you're using Rails, go for Jammit.

> --
> You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
> To post to this group, send email to rails-...@googlegroups.com.
> To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.
>
>

--
http://crazyhollywood.org

George

unread,
Jun 22, 2010, 2:12:00 PM6/22/10
to rails-...@googlegroups.com
On Tue, Jun 22, 2010 at 7:50 AM, Steven Ringo <goo...@stevenringo.com> wrote:
> Hi All,
>
> Just wanted to find out how folks are organising javascript code &
> files in rails apps, and address things such as:
>
> 1. Not polluting the global namespace. Seems to be divided opinion on
> using object literals vs. prototypal inheritance vs. Crockford's
> module pattern.
> 2. Separating code into files that are relevant to the server side
> code e.g. hooking into rails' naming conventions, and having 1 js file
> per view or controller.
> 3. Minifying and combining files in production.

We're using a tool which a (former) colleague of ours created. It's a
very impressive hack IMO, although I'm on the fence as to whether or
not it's a good idea overall. I probably wouldn't recommend it for
smaller projects:

http://github.com/adamh/html_namespacing

The idea is you can write CSS and javascript that's scoped to a
particular *partial*. So:

* The CSS for app/views/path/to/template is in
app/stylesheets/views/path/to/template
* The JS for app/view/path/to/template is in
app/javascripts/views/path/to/template

It does this by inserting a class name (based on the template path) to
the toplevel elements of each partial, and then:

* for CSS: prefixing each rule with this class, so they only apply to
that part of the DOM
* for JS: providing a jquery object $NS(), which returns a jquery
object containing those elements, so you can look up elements just in
that part of the DOM using $.find().

The HTML modification is done by wrapping calls to render and scanning
the HTML using a C extension (so it's pretty fast, and only MRI/REE
compatible so far). You can then insert the CSS/JS for just the
rendered partials using a single helper call.

We've been using it for over a year, and I think it's done wonders for
managing development complexity. It has gotten in our way a little
when trying to do aggressive caching, or bundling asset (css, js)
files into libraries. It would also have a slight hit (not sure how
much) on JS performance, as all jquery selector lookups are prefixed
with an extra namespace class.

To deal with the bundling, we include all our "namespaced" JS and CSS
inline to avoid requiring a second set of user-and-page-specific
css/js files (throwing all the namespaced JS and CSS into the
site-wide css/js files was making it way too big). The rest of our JS
and CSS is minified and bundled using another gem he open-sourced:

http://github.com/adamh/asset_library

Hope that helps! Would of course love to hear impressions if anyone
gives either of these a go.

George

Clifford Heath

unread,
Jun 22, 2010, 9:57:38 PM6/22/10
to rails-...@googlegroups.com
On 22/06/2010, at 11:48 PM, Julio Cesar Ody wrote:
> http://sydjs-architecting.heroku.com/

Excellent, thanks Julio. It's really nice to see the alternatives
distilled into such a clear presentation. I've seen so many
variations of "objects in JS" that I wasn't sure how best to do
it.

Clifford Heath.

Steven Ringo

unread,
Jun 22, 2010, 9:49:20 PM6/22/10
to Ruby or Rails Oceania
@julio => Thanks for that. I think your preso covers just about
everything. I will have a look in more detail.

Maybe if you explain what you mean a bit more here, not so much in
terms of the code structure but more about the file structure.

> Write your JS as a client to the
> server's API. E.g.: a table you can use to read/write data is an app
> in itself. While it may appear in, say, FruitsController#index, I
> wouldn't have it mixed up with something else.

@George => I will have a look at your (colleague's) approach. Thanks
heaps.

Steve

Julio Cesar Ody

unread,
Jun 24, 2010, 1:19:16 AM6/24/10
to rails-...@googlegroups.com
I'm suggesting one file per "Javascript application", and that your
interface may be comprised of many of those. Another example: at the
top right hand corner of your dashboard page there's a section which
allows a user to quickly edit parts of his profile. That in itself
should be a separate Javascript app, sitting in it's own file.

It doesn't matter if you have a bunch of those. As long as these
applications can all be retrieved with a single request (read: you're
bundling/grouping your Javascripts) when in production, you're set.

Might as well pimp it while we're on the subject :), so here goes a
different solution than Jammit ->
http://github.com/juliocesar/rack-bundle

Though I recommend Jammit if you're using Rails.

Dylan Fogarty-MacDonald

unread,
Jun 24, 2010, 1:35:56 AM6/24/10
to rails-...@googlegroups.com
Currently I'm finding myself making classes or jQuery plugins for individual screens. As time goes on I'll move parts into their own classes or plugins to DRY things up across the app and take advantage of opportunities to form tight little reusable modules - i.e. an AJAX uploader or something for polling. On new applications I'm putting things within a single global variable, but on existing applications that task is not really on the radar yet.

I'm really keen to find a golden solution that suits me. This has been on my mind for a while. Hopefully soon I'll be closer to that place, but at the moment I feel like I'm trying out different approaches. I think building on experience in OO JavaScript will help.

Dylan

Dylan Fogarty-MacDonald

unread,
Jul 19, 2010, 9:26:41 AM7/19/10
to rails-...@googlegroups.com
Just stumbled across this post which is a good read: http://alexsexton.com/?p=51

Dylan

Korny Sietsma

unread,
Jul 19, 2010, 9:42:27 PM7/19/10
to rails-...@googlegroups.com
Nice.
It'd be good if more of these discussions talked about testability though.  It seems it should be an important concern when structuring your javascript code - how easy is it to test the code outside a browser...

Incidentally, I stumbled across a nice post on testing Raphael-based code:
and a follow up on doing the same with a mocking framework:

- Korny
Kornelis Sietsma  korny at my surname dot com
kornys on twitter/fb/gtalk/gwave www.sietsma.com/korny
"Every jumbled pile of person has a thinking part
that wonders what the part that isn't thinking
isn't thinking of"

Dylan Fogarty-MacDonald

unread,
Jul 19, 2010, 9:49:54 PM7/19/10
to rails-...@googlegroups.com
Thanks for the links Korny. 
This article seems to address what you're after: http://www.adequatelygood.com/2010/7/Writing-Testable-JavaScript

Dylan

Julio Cesar Ody

unread,
Jul 19, 2010, 9:56:20 PM7/19/10
to rails-...@googlegroups.com
I stumbled across this tweet today: http://twitter.com/julio_ody/status/18951903615  Oh wait, that's my own tweet.

Just one thing to bear in mind when doing headless testing. If portability is important, you'll wanna make sure that testing gets done not only on one engine. jSpec supports actual browser testing (invokes whatever browser you have installed and runs the specs using it). Which is good, but I thought I should mention that jSpec is no longer maintained by the author, or for that matter, by anyone I know.

Also, and I'll admit up front that may be out of noobness, but depending on the sort of crazy you're doing in the DOM, you will have a hard time getting it to work with jSpec (been there, done that). jSpec presents it's own interface when running specs, and you're supposed to use a sandbox of sorts when loading your own HTML. I had specs fail that "manual" testing proved were working. That happened to a point that I dropped it altogether. The approach other libraries take is to load the test suite on the real screen the app is running, which is a lot less problem prone.

And my response to the link Dylan just sent: *do* use closures. But make sure you export the functions you want to test to an object that's visible outside of it.

Harvey

unread,
Jul 20, 2010, 7:58:48 PM7/20/10
to Ruby or Rails Oceania
Here is my 2 cents on how I organise my Javascript files using a MVC.

http://codeniche.com/basic-javascript-mvc-pattern/

When it comes to testing I'm pretty happy using a Cucumber, Capybara
and Selenium combination to write integration tests.

- Scott

Mark Ratjens

unread,
Jul 20, 2010, 10:14:03 PM7/20/10
to rails-...@googlegroups.com
Scott,

I think re-applying the MVC pattern is exactly the right thing to do. You're applying the principal of *holonic organisation* which argues, at its simplest, that objects of any granularity within a system should show self-similar structures through all levels. Systems with objects whose structure vary depending on their size or position in a system tend to produce a brittle system. *Holonic" systems tend to be more scalable and re-configurable, and it is usually easier to take a holonic component from one system and fit it in another, as long as both exhibit the same holonic structure.

MVC is a profound structure that I believe should be visible at all levels of an app. In Rails, we already have it enshrined as the highest level architecture. Since the advent of Rails Engines, we can repeat the same structure in plugins. And we can do more. As you have pointed out, it applies to the app's javascript. It can also apply to the structure of CSS ... and anywhere else you happen to look and wonder if something could be structured better. For example, even model classes can exhibit the MVC pattern internally, if you care to look at them that way.

I've been toying around with doing a preso on this at RORO sometime ....

cheers

Mark Ratjens


--

Mikel Lindsaar

unread,
Jul 21, 2010, 12:10:46 AM7/21/10
to rails-...@googlegroups.com
On 21/07/2010, at 12:14 PM, Mark Ratjens wrote:
> I've been toying around with doing a preso on this at RORO sometime ....

+1

Mikel

chrisjacob

unread,
Jul 21, 2010, 7:44:15 PM7/21/10
to Ruby or Rails Oceania
> I've been toying around with doing a preso on this at RORO sometime ....

+1 (and post it on slideshare)

Chris

chrisjacob

unread,
Jul 21, 2010, 7:49:14 PM7/21/10
to Ruby or Rails Oceania
@Scott the GitHub link in your article was incorrect.

Here's the correct url for anyone else looking:
http://github.com/codeniche/javascript-mvc-pattern

Korny Sietsma

unread,
Jul 21, 2010, 8:04:08 PM7/21/10
to rails-...@googlegroups.com
Isn't this a bit of a golden hammer approach though?  Surely MVC is not the one true architecture for everything...

- Korny

Jonathan Clarke

unread,
Jul 21, 2010, 8:30:29 PM7/21/10
to rails-...@googlegroups.com
BLASPHEMY...

Lachlan Hardy

unread,
Jul 21, 2010, 8:32:48 PM7/21/10
to rails-...@googlegroups.com
Shun the non-believer!

SHUUUUUUUUUUNNNNNNNNN!

David Parry

unread,
Jul 21, 2010, 8:38:32 PM7/21/10
to rails-...@googlegroups.com
On 22/07/2010, at 10:04 AM, Korny Sietsma wrote:
> Isn't this a bit of a golden hammer approach though? Surely MVC is not the one true architecture for everything...

I seem to recall Dave Thomas saying in his recent talk that MVC was a workaround because the machine it was developed on didn't have proper interrupt handling, so they couldn't use event-based processing.

Clifford Heath

unread,
Jul 21, 2010, 8:48:42 PM7/21/10
to rails-...@googlegroups.com
On 22/07/2010, at 10:04 AM, Korny Sietsma wrote:
> Isn't this a bit of a golden hammer approach though? Surely MVC is
> not the one true architecture for everything...

I think the important thing about what's proposed here isn't about
putting
the M/V/C parts into separate files, but about separating those roles
at all.

That is, the "M" part describes a passive box of state and capability,
the
C part activates those capabilities, and the V part displays the state.

There are many ways to implement this separation, and it doesn't have to
be as heavy-weight as some of the approaches proposed. The important
thing is the mental discipline imposed by separating them conceptually.

Clifford Heath, Data Constellation, http://dataconstellation.com
Agile Information Management and Design.

Josh Price

unread,
Jul 21, 2010, 8:59:50 PM7/21/10
to rails-...@googlegroups.com
On 22/07/2010, at 10:48 AM, Clifford Heath wrote:
> On 22/07/2010, at 10:04 AM, Korny Sietsma wrote:
>> Isn't this a bit of a golden hammer approach though? Surely MVC is not the one true architecture for everything...
>
> I think the important thing about what's proposed here isn't about putting
> the M/V/C parts into separate files, but about separating those roles at all.
>
> That is, the "M" part describes a passive box of state and capability, the
> C part activates those capabilities, and the V part displays the state.

I really like this approach. The trickiest part of having the DOM involved in JS is that the DOM can simultaneously be the Model *and* the View. This structure forces to you to separate that duality.

> There are many ways to implement this separation, and it doesn't have to
> be as heavy-weight as some of the approaches proposed. The important
> thing is the mental discipline imposed by separating them conceptually.

With Jammit, Sprockets and other JS managers, the folder separation is not an issue for production but makes the approach taken extremely clear.

The fact that it mirrors Rails' own structure makes me have to think about it less. Time for an opinionated JS structure in Rails perhaps? ;)

Josh

Korny Sietsma

unread,
Jul 21, 2010, 9:06:03 PM7/21/10
to rails-...@googlegroups.com
Yeah, he said that - I filed it under "One of Dave Thomas' amusing but mostly untrue anecdotes" :)

In "Patterns of Enterprise App Architecture" they mention that the View gets updated by Model changes using  an implementation of the Observer pattern "such as event propagation or a listener" - so event-driven isn't really an alternative to MVC.

Of course, in web-based MVC, you don't get automated view updates at all - it'd be interesting to see whether you could do this (and whether it'd be worthwhile!) in a Javascript app.

- Korny


--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To post to this group, send email to rails-...@googlegroups.com.
To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.

Clifford Heath

unread,
Jul 21, 2010, 9:09:19 PM7/21/10
to rails-...@googlegroups.com
On 22/07/2010, at 10:59 AM, Josh Price wrote:
> The fact that it mirrors Rails' own structure makes me have to think
> about it less. Time for an opinionated JS structure in Rails
> perhaps? ;)

I don't think that "Jails" is ever going to catch on ;-)

Korny Sietsma

unread,
Jul 21, 2010, 9:09:41 PM7/21/10
to rails-...@googlegroups.com
Very true - and a good summary.  My fear on people suggesting MVC as a golden hammer is the heavy-weight overly-complex approach that I remember from the good ol' days of gui programming - often more time was spent coding complex interactions between M and V than was spent actually building stuff that worked.  My golden hammer these days is YAGNI.

Though I completely agree that separation of Model and Presentation is a key concept that is usually something you *are* gonna need.

- Korny


--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To post to this group, send email to rails-...@googlegroups.com.
To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.

Scott Harvey

unread,
Jul 21, 2010, 9:10:44 PM7/21/10
to Ruby or Rails Oceania
> The fact that it mirrors Rails' own structure makes me have to think about it less

This is exactly the reason I use MVC for my Javascript files, it means
one less concept to wrap my head around.

There may well be a better solution if you are writing a very large
Javascript based application but if you are just looking for a way to
keep your Javascript files neat and tidy I've found the MVC concept
works well.

Scott

Clifford Heath

unread,
Jul 21, 2010, 9:20:39 PM7/21/10
to rails-...@googlegroups.com
On 22/07/2010, at 10:59 AM, Josh Price wrote:
>> That is, the "M" part describes a passive box of state and
>> capability, the
>> C part activates those capabilities, and the V part displays the
>> state.
> I really like this approach. The trickiest part of having the DOM
> involved in JS is that the DOM can simultaneously be the Model *and*
> the View. This structure forces to you to separate that duality.

MVC originally served the purpose of each model serving an unknown
number of views of potentially disparate types. In most situations
that doesn't happen and isn't needed however, and the value of
separating the model from the view is less. If the Model is a JS object,
and the view is a DOM object, and they're closely coupled one-to-one,
that serves most purposes. So on that I'd agree with Korny.

If you have a bar chart with values above each bar, there's no need to
separate (for example) the bar height from the displayed value, as two
separate views - it's simply overkill. Do it as one view instead.

It's really important that the model is passive and the controller
separate.
That's what makes it possible to configure the model through settings,
and tweak the behaviour by changing the controller. Finer-grained
customisation is usually not needed, since we have CSS to set most
view details.

Michael Gall

unread,
Jul 21, 2010, 9:40:34 PM7/21/10
to rails-...@googlegroups.com
On Thu, Jul 22, 2010 at 1:10 PM, Scott Harvey <scottand...@gmail.com> wrote:
> The fact that it mirrors Rails' own structure makes me have to think about it less

This is exactly the reason I use MVC for my Javascript files, it means
one less concept to wrap my head around.

Personally I think of my client side files as MVC. The html/dom is the M, the CSS is the V and Javascript is the C.
 

--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To post to this group, send email to rails-...@googlegroups.com.
To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.




--
Checkout my new website: http://myachinghead.net
http://wakeless.net

Mark Ratjens

unread,
Jul 21, 2010, 9:50:56 PM7/21/10
to rails-...@googlegroups.com
Good to see this thread has sparked a good debate.

I was deliberately light on implementation details in my last post ... ambiguity tends to generate more ideas :-)

Now, just to be clear, I was proposing MVC as a *pattern* that applies to holons. A pattern is not an implementation. There can be many implementations derived from a single pattern. Dividing MVC components into separate files is one implementation, but it's not necessarily required by the pattern.

Software architecture is, among other things,  about the *separation of concerns*. You could say that MVC says separate out M stuff, V stuff and C stuff from each other ... don't put it in the same "space." The size of the original holon (*space*) indicates how much separation is required ... it should be proportional.

So, at the app level, we've grown accustomed to dividing MVC into their own folders at the highest level.

In a single class, applying MVC may be as simple as putting the api of the class at the top, supporting algorithms in the middle and private and state stuff at the bottom.

Then there are holons that are so small that it's just not worth applying the pattern ... until the holon grows in size or complexity. Some of the counter examples in this thread clearly fall into this category.

MVC is one of those enduring patterns. It's been around since the late '70s. Like most profound things, it's almost so obvious that you don't see it. It's as banal as saying a book has a beginning, a middle and an end. Chapters have beginnings, middles and ends. Larger paragraphs probably do too. This one does ... check it out! :-)

@Korny ... yes, there's a danger someone might make a golden hammer out of my advice. I'm hoping most people can take an idea and know when the context is right to use it. Anyone that wants to see one side of this thread as saying "Apply MVC everywhere without question," is entitled to reap the experience they sow.

What I know is asking this question: *Could MVC help me clean this up* is a useful step, even if the answer is, *Not yet*

Bayan Khalili

unread,
Jul 21, 2010, 11:40:35 PM7/21/10
to Ruby or Rails Oceania
> Of course, in web-based MVC, you don't get automated view updates at all -
> it'd be interesting to see whether you could do this (and whether it'd be
> worthwhile!) in a Javascript app.

If you're talking about data binding in web apps, you get this in
Flash/Flex and Sproutcore. I'm mostly familiar with Flex's
databinding, and have to say it's a huge convenience. It's a core
ingredient to many of the Actionscript frameworks (which are all MVC
as far as I'm aware).

Does anyone have any experience using this technique in javascript?

Bayan

Michael Koukoullis

unread,
Jul 22, 2010, 11:21:13 AM7/22/10
to Ruby or Rails Oceania
Dave Thomas sure did say that when he was in Sydney last.

> I seem to recall Dave Thomas saying in his recent talk that MVC was a workaround because the machine it was developed on didn't have proper interrupt handling, so they couldn't use event-based processing.

For me the question here isn't whether or not MVC is a good or bad
pattern for application JavaScript, but whether it's the appropriate
spring loaded solution to implement the necessary interactions and
functions within an app. If you've spent more than a new york minute
thinking about those interactions and functions, you're likely to find
that a stack of alternate approaches are required for an elegant
implementation. Adopt a wholesale approach and you'll silently force
your brain into a sub-optimal design choice - scary thing being you
wont even know.

This is a very interesting discussion.

Mark Ratjens

unread,
Jul 22, 2010, 10:17:16 PM7/22/10
to rails-...@googlegroups.com
MVC is a pattern. It's a different animal in an old Smalltalk client/server app than it is in a webserver app than it is in Javascript. BUt you can still see it there if you choose.

 Well written-apps derived their implementation from a great many patterns. Adding more patterns does not invalidate the fact that others are there.

There is no doubt that Controllers especially hide a multitude of sins. You can certainly find more to do on the inside of them and their interactions, especially with views.

Let's look at the long-gone MacApp framework for a second. Rather than propose a controller that encapsulated a set of actions, it proposed a Command class that encapsulated a single action. There are advantages to this: you couls give a command state, which you could manipulate much like a model object. That made it easy to undo, redo, log an audit trail and even save the state so the command could be executed later (e.g in a batch job or according to a schedule).

So there  you go: two frameworks, two implementations. But it's flakey thinking to fall into a MacApp versus MVC dualism. Both patterns can happily co-exist in one app. In MacApp, controllers don't exist as classes, but they can exist as groups of commands. In MVC, you can implement actions inside controllers as separate classes with their own state ... a good idea in many cases.

There is nothing stopping anyone from added more patterns to solve whatever impediments you see in any implementation of MVC ... but you can't make it go away. An application has a beginning, a middle, and an end. If you wish to add more features or more rules of how the bits interact, then may the architecture gods smile upon you.

@Michael ... labeling this thinking as "a wholesale approach" is empty rhetoric. I am the last person to espouse dogma. Nothing I do is "wholesale." Your assertion is innaccurate. I would prefer if you argued well-framed points rather than glibly throwing alternative argument into a bucket with a label of your own choosing.

Holonic self-similarity is a powerful idea. It informs many disciplines far-removed from our own, including organisational structure and biology. In the human body, a cell in the appendix has a similar structure to a neuron in the brain, as well as obvious differences. There is an evident pattern in both. There is a cell wall, a middle with a bunch of stuff in it, and a nucleus.

I can't help but feel that many participants in this group would prefer to argue about the uselessness of the appendix, rather than wonder at how very complex systems tend to exhibit self-similarity at all levels.

Reply all
Reply to author
Forward
0 new messages